#if !defined(MGLISTIMPL_H_INCLUDED)
#define MGLISTIMPL_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "MGList.h"

/// define a data structure which is used to store mouse gesture command in a list
typedef class CGestureCommand : public GESTURE_BASE
{
public:
	// c'tor and d'tor
	CGestureCommand();
	CGestureCommand(const CMGPattern &rPattern, WORD wID, LPCTSTR pszID, LPCTSTR pszDesc, BYTE bCatID = 0);
	CGestureCommand(LPCTSTR pszPattern, WORD wID, LPCTSTR pszID, LPCTSTR pszDesc, BYTE bCatID = 0);
	~CGestureCommand();
	CGestureCommand(const CGestureCommand &rRhs);
	CGestureCommand &operator =(const CGestureCommand &rRhs);

public:
	WORD cbExtra;
	LPBYTE pbExtra;
} GESTURE, far *LPGESTURE;

#pragma warning(push)

#include <yvals.h>

#pragma warning(disable: 4100)
#pragma warning(disable: 4284)
#pragma warning(disable: 4710)
#pragma warning(disable: 4786)

#include <list>
#include <algorithm>

class CMGListImpl
{
public:
	CMGListImpl();
	virtual ~CMGListImpl();

	void Cleanup();

public:
	int Add(LPGESTURE pGesture, BYTE bCatTarget = 0);
	
	LPGESTURE Get(int nIndex, BYTE bCatTarget = 0);

	int Find(LPCTSTR pszGesture, BYTE bCatTarget = 0);
	int Find(WORD wID, BYTE bCatID = 0);
	
	BOOL Remove(LPCTSTR pszGesture, BYTE bCatTarget = 0);
	BOOL Remove(int nIndex, BYTE bCatTarget = 0);
	
	void Empty();

	std::tstring GetAsString(int nIndex, BYTE bCatTarget = 0);
	int AddFromString(LPCTSTR pszString);

	BOOL Load(LPCTSTR pszFilePath);
	BOOL Save(LPCTSTR pszFilePath);
	void UpdateRegistry(BOOL bSaveAndValidate = TRUE);

	int GetCount(BYTE bCatTarget = 0);

public:
	WORD GetMouseCmd(LPCTSTR pszKey, BYTE bCatTarget = 0);
	
	std::tstring GetCommandDesc(WORD wCommand);
	std::tstring GetCommandID(WORD wCommand);
	BYTE GetCommandCat(WORD wCommand);

	TCHAR GetKeyMark(enum MG::KeyDef key) const;
	TCHAR GetArrowMark(enum MG::ArrowDef arrow) const;

protected:
	int Add(LPCTSTR pszGesture, WORD wID, LPCTSTR pszID, LPCTSTR pszDescription, BYTE bCatTarget = 0, BYTE bCatID = 0);
	int Find(LPCTSTR pszGesture, std::list<LPGESTURE>::iterator &it);
	int FindInsertAfter(LPCTSTR pszGesture, std::list<LPGESTURE>::iterator &it);
	
private:
	struct MGLIST : std::list<LPGESTURE>
	{
		// functor to delete the object from memory
		struct Delete_t
		{
			void operator() (LPGESTURE pGesture)
			{
				delete pGesture;
				pGesture = NULL;
			}
		};
	} m_list;

	int m_nIndexFoundCached;

	// 0, WheelUp
	// 1, WheelDown
	// 2, Button1Up (L Button)
	// 3, Button2Up (M or R Button)
	static const TCHAR tchKey[];
	
	// 0, ArrowRight
	// 1, ArrowUp
	// 2, ArrowLeft
	// 3, ArrowDown
	static const TCHAR tchArrow[];
};

#pragma warning(pop)

#endif	// #if !defined(MGLISTIMPL_H_INCLUDED)